#pragma once
#include <glad/glad.h>
#include <stb_image.h>
#include "baseClass/GLGlobal.h"
#include "baseClass/Picture.h"
  
#include <thread>

class Texture2D
{
private:
    /* data */
    
public:

    uint32_t id = 0;
 
    Texture2D(){};
    Texture2D(const Texture2D& other) = delete;


    Texture2D( Texture2D&& other) noexcept
    {
        this->id = other.id;
    }


    Texture2D(const char *path)
    {
       
        stbi_set_flip_vertically_on_load(true);
        int width, height, nrChannels;
        unsigned char *data = stbi_load(path, &width, &height, &nrChannels, 0);

        auto mtx = GLGlobal::GetMuetx();
        std::lock_guard<std::mutex> lock(*mtx);

        glGenTextures(1, &id);
        glBindTexture(GL_TEXTURE_2D, id);
      
        if(nrChannels == 3)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        else if(nrChannels == 4)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);

        stbi_image_free(data);
    }

    Texture2D(uint8_t *data,size_t width,size_t height,size_t formtype)
    {   
       this->Init(data,width,height,formtype);
    }

    Texture2D(Picture &pic)
    {
        this->Init(pic.data,pic.width,pic.height,pic.formtype);
    }
  
    /// @brief 线程安全
    void Init(uint8_t *data,size_t width,size_t height,size_t formtype)
    {
        auto mtx = GLGlobal::GetMuetx();
        std::lock_guard<std::mutex> lock(*mtx);
        glGenTextures(1, &id);
        glBindTexture(GL_TEXTURE_2D, id);
        glTexImage2D(GL_TEXTURE_2D, 0, formtype, width, height, 0, formtype, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);

    }

    /// @brief 线程不保护
    /// @param n 
    void bind(int n)
    {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glActiveTexture(GL_TEXTURE0+n);
        glBindTexture(GL_TEXTURE_2D, id);
    }



    ~Texture2D()
    {
        glDeleteTextures(1, &id);
    }
};




